package com.ruoyi.finance.domain;

import net.sourceforge.tess4j.*;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WalmartPDFValidator {

    public static class PdfSummaryData {
        public String startDate;
        public String endDate;
        public BigDecimal salesTotal = BigDecimal.ZERO;
        public BigDecimal refundsTotal = BigDecimal.ZERO;
        public BigDecimal wfsTotal = BigDecimal.ZERO;
        public BigDecimal otherActivitiesTotal = BigDecimal.ZERO;

        @Override
        public String toString() {
            return "日期：" + startDate + " - " + endDate + "\n" +
                    "Sales：" + salesTotal + "\n" +
                    "Refunds：" + refundsTotal + "\n" +
                    "WFS：" + wfsTotal + "\n" +
                    "Other：" + otherActivitiesTotal;
        }
    }

    public PdfSummaryData extractFromPdfWithOCR(File pdfFile) throws Exception {
        PdfSummaryData result = new PdfSummaryData();

        try (PDDocument document = PDDocument.load(pdfFile)) {
            PDFRenderer renderer = new PDFRenderer(document);
            Tesseract tesseract = new Tesseract();

            // 设置 Tesseract 路径
            tesseract.setDatapath("/usr/share/tesseract/tessdata");//("E:/Tesseract/tessdata");
            tesseract.setLanguage("eng");

            StringBuilder allText = new StringBuilder();

            for (int i = 0; i < document.getNumberOfPages(); i++) {
                BufferedImage image = renderer.renderImageWithDPI(i, 300); // 高分辨率
                File imageFile = new File("page-" + i + ".png");
                ImageIO.write(image, "png", imageFile);

                String text = tesseract.doOCR(imageFile);
                allText.append(text).append("\n");

                imageFile.delete(); // 处理完删除临时图片
            }

            String ocrText = allText.toString();

            // 提取日期：如 "Mar 8, 2025 - Mar 22, 2025"
            Matcher m = Pattern.compile("(\\w+ \\d{1,2}, \\d{4})\\s*-\\s*(\\w+ \\d{1,2}, \\d{4})").matcher(ocrText);
            if (m.find()) {
                SimpleDateFormat srcFmt = new SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH);
                SimpleDateFormat tgtFmt = new SimpleDateFormat("yyyy-MM-dd");
                result.startDate = tgtFmt.format(srcFmt.parse(m.group(1)));
                result.endDate = tgtFmt.format(srcFmt.parse(m.group(2)));
            }

            // 提取金额
            List<BigDecimal> totals = extractAllTotals(ocrText);
            // 假设第一项是 Sales 总额，第二项是 Refunds 总额
            if (totals.size() > 0) {
                result.salesTotal = totals.get(0); // 第一个值是 Sales
            }
            if (totals.size() > 1) {
                result.refundsTotal = totals.get(1); // 第二个值是 Refunds
            }
            if (totals.size() > 2) {
                result.wfsTotal = totals.get(2); // 第三个值是 WFS (如果存在)
            }
            if (totals.size() > 3) {
                result.otherActivitiesTotal = totals.get(3); // 第四个值是 Other Activities (如果存在)
            }

            return result;
        }
    }

    public static List<BigDecimal> extractAllTotals(String ocrText) {
        List<BigDecimal> totals = new ArrayList<>();

        // 正则表达式匹配所有的 Total: 金额
        String regex = "Total[:：]?\\s*-?\\$\\s*([\\d,]+(?:\\.\\d{1,2})?)\\s*";

        Matcher matcher = Pattern.compile(regex).matcher(ocrText);

        while (matcher.find()) {
            String amountStr = matcher.group(1).replace(",", "").trim(); // 去掉逗号并去除空格
            totals.add(new BigDecimal(amountStr));  // 将匹配的金额添加到列表中
        }

        return totals;
    }
    @Transactional
    public void validateWithDatabase(WalmartProfitReport wp, PdfSummaryData pdfData,
                                     BigDecimal salesSum, BigDecimal refundsSum,
                                     BigDecimal wfsSum, BigDecimal adSemSum) {

        // 日期修正：PDF endDate 减一天
        String pdfEndDate = pdfData.endDate;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date date = sdf.parse(pdfEndDate);
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
            cal.add(Calendar.DATE, -1); // 👈 减一天
            pdfEndDate = sdf.format(cal.getTime());
        } catch (Exception e) {
            //throw new RuntimeException(" PDF 结束日期格式错误：" + pdfEndDate);
        }

        // 比较修正后的日期
//        String pdfStart = pdfData.startDate;
//        String dbStart = new SimpleDateFormat("yyyy-MM-dd").format(wp.getStartDate());
//        String dbEnd = new SimpleDateFormat("yyyy-MM-dd").format(wp.getEndDate());
//
//        if (!pdfStart.equals(dbStart) || !pdfEndDate.equals(dbEnd)) {
//            throw new RuntimeException(" 日期不一致：PDF(" + pdfStart + " ~ " + pdfEndDate + ") ≠ 数据库(" + dbStart + " ~ " + dbEnd + ")");
//        }

        // 校验销售合计
        if (pdfData.salesTotal.compareTo(salesSum.abs()) != 0) {
            throw new RuntimeException(" Sales 总额不一致：PDF(" + pdfData.salesTotal + ") ≠ 系统明细(" + salesSum + ")");
        }

        // 校验退款合计
        if (pdfData.refundsTotal.compareTo(refundsSum.abs()) != 0) {
            throw new RuntimeException(" Refunds 总额不一致：PDF(-" + pdfData.refundsTotal + ") ≠ 系统明细(" + refundsSum + ")");
        }

        // 校验履约服务合计
        if (pdfData.wfsTotal.compareTo(wfsSum.abs()) != 0) {
            throw new RuntimeException(" WFS 总额不一致：PDF(-" + pdfData.wfsTotal + ") ≠ 系统明细(" + wfsSum + ")");
        }

        // 校验广告和 SEM 合计
        if (pdfData.otherActivitiesTotal.compareTo(adSemSum.abs()) != 0) {
            throw new RuntimeException(" Other Activities 总额不一致：PDF(-" + pdfData.otherActivitiesTotal + ") ≠ 系统明细(" + adSemSum + ")");
        }

    }

    private String cleanOCRText(String ocrText) {
        // 去除多余的换行符、空格，确保格式一致
        ocrText = ocrText.replaceAll("\\s+", " "); // 替换所有连续空白字符为单一空格
        ocrText = ocrText.replaceAll("= LAist", ""); // 去除 OCR 输出中的不需要的部分
        return ocrText;
    }

    private BigDecimal extractAmount(String ocrText, String regex) {
        // 清理 OCR 文本
        ocrText = cleanOCRText(ocrText);

        Matcher matcher = Pattern.compile(regex).matcher(ocrText);
        if (matcher.find()) {
            String amountStr = matcher.group(1).replace(",", "").trim();  // 去掉逗号并去除空格
            return new BigDecimal(amountStr);
        }
        return BigDecimal.ZERO;
    }

    // 保存 PDF 文件并将其转换为合并的 PNG 图片
    public static String savePdfWithDate(MultipartFile file, String profilePath) throws IOException {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        String datePath = today.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));

        // 构建存储路径，按相对路径进行拼接
        String fullPath = profilePath + "/upload/" + datePath;

        // 创建目录，如果目录不存在则创建
        File dir = new File(fullPath);
        if (!dir.exists()) {
            dir.mkdirs(); // 创建目录
        }

        // 保存文件
        String fileName = file.getOriginalFilename();
        File destFile = new File(dir, fileName);

        // 将文件保存到指定目录
        //file.transferTo(destFile);

        // 获取文件名，不包括扩展名
        String baseFileName = fileName.substring(0, fileName.lastIndexOf("."));

        // PDF 转图片
        convertPdfToImage(destFile, fullPath, baseFileName);

        String dbPath = "/profile/upload/" + datePath + "/" + baseFileName + ".png";

        // 返回数据库存储路径（相对路径）
        return dbPath;
    }

    // 将 PDF 转换为合并后的 PNG 图片
    private static void convertPdfToImage(File pdfFile, String outputDir, String baseFileName) throws IOException {
        try (PDDocument document = PDDocument.load(pdfFile)) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);

            // 创建一个空的图像来保存合并后的图片
            int totalHeight = 0;
            int maxWidth = 0;

            // 遍历所有页面，计算出合并后图片的高度和宽度
            for (int pageIndex = 0; pageIndex < document.getNumberOfPages(); pageIndex++) {
                BufferedImage pageImage = pdfRenderer.renderImageWithDPI(pageIndex, 300); // 使用300 DPI来增加清晰度
                totalHeight += pageImage.getHeight();
                maxWidth = Math.max(maxWidth, pageImage.getWidth());
            }

            // 创建一个合并的图片
            BufferedImage combinedImage = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
            Graphics g = combinedImage.getGraphics();

            int yOffset = 0;
            // 再次遍历所有页面，将每一页图片粘贴到合并的图像中
            for (int pageIndex = 0; pageIndex < document.getNumberOfPages(); pageIndex++) {
                BufferedImage pageImage = pdfRenderer.renderImageWithDPI(pageIndex, 300); // 使用300 DPI来增加清晰度
                g.drawImage(pageImage, 0, yOffset, null);
                yOffset += pageImage.getHeight();
            }

            // 保存为PNG文件
            File combinedImageFile = new File(outputDir, baseFileName + ".png");
            ImageIO.write(combinedImage, "PNG", combinedImageFile);

        }
    }

}
